/* eslint-disable react-hooks/exhaustive-deps */
import React, { useState, useEffect, useRef, useCallback } from 'react';
import io, { Socket } from 'socket.io-client';
import {
  AudioOutlined,
  AudioMutedOutlined,
  VideoCameraOutlined,
  VideoCameraAddOutlined,
  DesktopOutlined,
  CloseCircleOutlined,
  PhoneOutlined,
  TeamOutlined,
  MessageOutlined,
  EditOutlined,
  CopyOutlined,
  StarOutlined,
  RiseOutlined,
  PlayCircleOutlined,
  PauseCircleOutlined,
  DownloadOutlined,
  HeartOutlined,
  SmileOutlined,
  DeleteOutlined,
} from '@ant-design/icons';
import { MdScreenShare, MdStopScreenShare, MdBrush } from 'react-icons/md';
import EmojiPicker from 'emoji-picker-react';
import type { EmojiClickData } from 'emoji-picker-react';

import MeetingTranscript from './MeetingTranscript';
import './MeetingRoom.css';

interface MeetingRoomProps {
  roomId: string;
  userId: string;
  userName?: string;
  localIP: string;
}

interface Peer {
  peerId: string;
  stream: MediaStream;
}

interface ChatMessage {
  type: 'system' | 'user';
  userId?: string;
  userName?: string;
  message: string;
  timestamp: number | string;
}

interface SignalData {
  senderId: string;
  signal: RTCSessionDescriptionInit | RTCIceCandidateInit;
}

// Define SimplePeer interface for the peer ref
interface SimplePeer {
  on: (event: string, callback: (data: unknown) => void) => void;
  signal: (data: unknown) => void;
  destroy: () => void;
}

// Extended RTCPeerConnection interface to include dataChannels
interface ExtendedRTCPeerConnection extends RTCPeerConnection {
  dataChannels?: { [userId: string]: RTCDataChannel };
}

interface WhiteboardAction {
  userId: string;
  userName?: string;
  action: 'draw' | 'clear';
  data?: {
    x: number;
    y: number;
    type: 'start' | 'move' | 'end';
    color: string;
    lineWidth: number;
  };
  timestamp: string;
}

// Fix Window interface declaration
declare global {
  interface Window {
    webkitAudioContext: typeof AudioContext;
  }
}

const MeetingRoom: React.FC<MeetingRoomProps> = ({
  roomId,
  userId,
  userName,
  localIP,
}) => {
  const [peers, setPeers] = useState<Peer[]>([]);
  const [videoEnabled, setVideoEnabled] = useState<boolean>(true);
  const [audioEnabled, setAudioEnabled] = useState<boolean>(true);
  const [screenSharing, setScreenSharing] = useState<boolean>(false);
  const [usersInRoom, setUsersInRoom] = useState<string[]>([]);
  const [showParticipants, setShowParticipants] = useState<boolean>(true);
  const [copied, setCopied] = useState<boolean>(false);
  const [showChat, setShowChat] = useState<boolean>(false);
  const [chatMessages, setChatMessages] = useState<ChatMessage[]>([]);
  const [newMessage, setNewMessage] = useState<string>('');
  const [unreadCount, setUnreadCount] = useState<number>(0);
  const [error, setError] = useState<string | null>(null);
  const [showWhiteboard, setShowWhiteboard] = useState<boolean>(false);
  const [isDrawing, setIsDrawing] = useState<boolean>(false);
  const [currentColor, setCurrentColor] = useState<string>('#000000');
  const [lineWidth, setLineWidth] = useState<number>(2);
  const [showTranscript, setShowTranscript] = useState<boolean>(false);
  const [isTranscriptRecording, setIsTranscriptRecording] =
    useState<boolean>(false);
  // whiteboardActions state is needed for history tracking
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const [whiteboardActions] = useState<WhiteboardAction[]>([]);
  const [showEmojiPicker, setShowEmojiPicker] = useState<boolean>(false);

  // 鲜花系统相关状态
  const [flowerCounts, setFlowerCounts] = useState<{
    [userId: string]: number;
  }>({});
  const [showFlowerPanel, setShowFlowerPanel] = useState<boolean>(false);
  const [selectedUserForFlower, setSelectedUserForFlower] = useState<
    string | null
  >(null);
  const [flowerAnimation, setFlowerAnimation] = useState<{
    [userId: string]: boolean;
  }>({});

  // 视频回放相关状态
  const [isRecording, setIsRecording] = useState<boolean>(false);
  const [showReplay, setShowReplay] = useState<boolean>(false);
  const [recordedBlobs, setRecordedBlobs] = useState<Blob[]>([]);
  const [replayVideoUrl, setReplayVideoUrl] = useState<string | null>(null);
  const [replayProgress, setReplayProgress] = useState<number>(0);
  const [isReplayPlaying, setIsReplayPlaying] = useState<boolean>(false);

  const userVideoRef = useRef<HTMLVideoElement>(null);
  const screenShareRef = useRef<MediaStream | null>(null);
  const peerConnectionsRef = useRef<{
    [key: string]: ExtendedRTCPeerConnection;
  }>({});
  const remoteVideoRefs = useRef<{ [key: string]: HTMLVideoElement | null }>(
    {}
  );
  const userStreamRef = useRef<MediaStream | null>(null);
  const socketRef = useRef<Socket | null>(null);
  // myPeerRef is needed for WebRTC connection initialization in some cases
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const myPeerRef = useRef<SimplePeer | null>(null);
  const chatContainerRef = useRef<HTMLDivElement>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const contextRef = useRef<CanvasRenderingContext2D | null>(null);
  const emojiPickerRef = useRef<HTMLDivElement>(null);

  // 视频录制相关refs
  const mediaRecorderRef = useRef<MediaRecorder | null>(null);
  const replayVideoRef = useRef<HTMLVideoElement>(null);
  const recordingStartTimeRef = useRef<number>(0);

  // 1. 定义高低码率和丢包率阈值
  const HIGH_BITRATE = 1500 * 1000; // 1.5Mbps
  const LOW_BITRATE = 300 * 1000; // 300kbps
  const LOSS_THRESHOLD = 0.05; // 丢包率5%
  const RECOVER_THRESHOLD = 0.01; // 丢包率1%
  const [currentBitrate, setCurrentBitrate] = useState(HIGH_BITRATE);

  // 2. 动态调整码率函数
  const setVideoBitrate = useCallback(
    async (pc: RTCPeerConnection, maxBitrate: number) => {
      const senders = pc.getSenders();
      const videoSender = senders.find(
        s => s.track && s.track.kind === 'video'
      );
      if (videoSender) {
        const parameters = videoSender.getParameters();
        if (!parameters.encodings) parameters.encodings = [{}];
        parameters.encodings[0].maxBitrate = maxBitrate;
        await videoSender.setParameters(parameters);
      }
    },
    []
  );

  // 3. 定时检测网络并动态降级
  useEffect(() => {
    const interval = window.setInterval(async () => {
      for (const pc of Object.values(peerConnectionsRef.current)) {
        const stats = await pc.getStats();
        stats.forEach(report => {
          if (report.type === 'outbound-rtp' && report.kind === 'video') {
            const packetsSent = report.packetsSent || 1;
            const packetsLost = report.packetsLost || 0;
            const lossRate = packetsLost / (packetsSent + packetsLost);
            // 降级
            if (lossRate > LOSS_THRESHOLD && currentBitrate !== LOW_BITRATE) {
              setVideoBitrate(pc, LOW_BITRATE);
              setCurrentBitrate(LOW_BITRATE);
              console.error('网络差，降级到低码率');
            }
            // 恢复
            if (
              lossRate < RECOVER_THRESHOLD &&
              currentBitrate !== HIGH_BITRATE
            ) {
              setVideoBitrate(pc, HIGH_BITRATE);
              setCurrentBitrate(HIGH_BITRATE);
              console.error('网络恢复，恢复高码率');
            }
          }
        });
      }
    }, 3000);
    return () => clearInterval(interval);
  }, [setVideoBitrate, currentBitrate, HIGH_BITRATE, LOW_BITRATE]);

  // 获取服务器URL
  const getServerUrl = useCallback((): string => {
    // 使用当前页面的协议和主机名
    const protocol = window.location.protocol;
    const host = window.location.hostname;
    const port = '3000'; // 后端端口
    return `${protocol}//${host}:${port}`;
  }, []);

  // 1. 美颜相关状态
  const [beautyEnabled, setBeautyEnabled] = useState(false);
  const [whitenStrength, setWhitenStrength] = useState(0.08); // 美白强度
  const [blurStrength, setBlurStrength] = useState(0.35); // 磨皮强度

  // 2. WebGL美颜渲染函数，支持动态参数
  const startBeautyFilter = useCallback(
    async (originStream: MediaStream, whiten = 0.08, blur = 0.35) => {
      const video = document.createElement('video');
      video.srcObject = originStream;
      video.muted = true;
      video.playsInline = true;

      try {
        await video.play();
      } catch (err) {
        console.error('视频播放失败:', err);
        return originStream; // 美颜失败，返回原始流
      }

      const width = 640;
      const height = 480;
      const canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;

      const gl = canvas.getContext('webgl');
      if (!gl) {
        console.error('无法创建WebGL上下文');
        return originStream;
      }

      // 创建着色器的函数
      function createShader(
        gl: WebGLRenderingContext,
        type: number,
        source: string
      ) {
        const shader = gl.createShader(type);
        if (!shader) {
          console.error('无法创建shader');
          return null;
        }
        gl.shaderSource(shader, source);
        gl.compileShader(shader);

        // 检查编译状态
        const compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
        if (!compiled) {
          const lastError = gl.getShaderInfoLog(shader);
          gl.deleteShader(shader);
          console.error('编译着色器错误:', lastError);
          return null;
        }
        return shader;
      }

      // 顶点着色器
      const vertexShaderSource = `
      attribute vec2 a_position;
      attribute vec2 a_texCoord;
      varying vec2 vTexCoord;
      void main() {
        gl_Position = vec4(a_position, 0, 1);
        vTexCoord = a_texCoord;
      }
    `;

      // 片元着色器（美白+简单磨皮）
      const fragmentShaderSource = `
      precision mediump float;
      varying vec2 vTexCoord;
      uniform sampler2D uSampler;
      uniform float whitenStrength;
      uniform float blurStrength;
      void main() {
        vec4 color = texture2D(uSampler, vTexCoord);
        color.rgb += whitenStrength;
        float blurSize = 1.0/512.0;
        vec4 sum = vec4(0.0);
        sum += texture2D(uSampler, vTexCoord + vec2(-blurSize, -blurSize));
        sum += texture2D(uSampler, vTexCoord + vec2( blurSize, -blurSize));
        sum += texture2D(uSampler, vTexCoord + vec2(-blurSize,  blurSize));
        sum += texture2D(uSampler, vTexCoord + vec2( blurSize,  blurSize));
        sum *= 0.25;
        color = mix(color, sum, blurStrength);
        gl_FragColor = color;
      }
    `;

      // 创建着色器
      const vertexShader = createShader(
        gl,
        gl.VERTEX_SHADER,
        vertexShaderSource
      );
      const fragmentShader = createShader(
        gl,
        gl.FRAGMENT_SHADER,
        fragmentShaderSource
      );

      // 检查着色器创建是否成功
      if (!vertexShader || !fragmentShader) {
        console.error('创建着色器失败');
        return originStream;
      }

      // 创建程序并链接
      const program = gl.createProgram();
      if (!program) {
        console.error('创建WebGL程序失败');
        return originStream;
      }

      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);

      // 检查链接状态
      const linked = gl.getProgramParameter(program, gl.LINK_STATUS);
      if (!linked) {
        const lastError = gl.getProgramInfoLog(program);
        console.error('链接程序错误:', lastError);
        gl.deleteProgram(program);
        gl.deleteShader(vertexShader);
        gl.deleteShader(fragmentShader);
        return originStream;
      }

      gl.useProgram(program);

      // 顶点数据
      const positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      gl.bufferData(
        gl.ARRAY_BUFFER,
        new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),
        gl.STATIC_DRAW
      );
      const positionLoc = gl.getAttribLocation(program, 'a_position');
      gl.enableVertexAttribArray(positionLoc);
      gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);

      // 纹理坐标
      const texCoordBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
      gl.bufferData(
        gl.ARRAY_BUFFER,
        new Float32Array([0, 1, 1, 1, 0, 0, 1, 0]),
        gl.STATIC_DRAW
      );
      const texCoordLoc = gl.getAttribLocation(program, 'a_texCoord');
      gl.enableVertexAttribArray(texCoordLoc);
      gl.vertexAttribPointer(texCoordLoc, 2, gl.FLOAT, false, 0, 0);

      // 纹理
      const texture = gl.createTexture();
      gl.bindTexture(gl.TEXTURE_2D, texture);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

      // uniform
      const whitenLoc = gl.getUniformLocation(program, 'whitenStrength');
      const blurLoc = gl.getUniformLocation(program, 'blurStrength');

      // 设置动画停止标志
      let animationStopped = false;

      // 渲染循环
      function render() {
        if (animationStopped || !gl) return;

        try {
          gl.uniform1f(whitenLoc, whiten);
          gl.uniform1f(blurLoc, blur);
          gl.bindTexture(gl.TEXTURE_2D, texture);
          gl.texImage2D(
            gl.TEXTURE_2D,
            0,
            gl.RGBA,
            gl.RGBA,
            gl.UNSIGNED_BYTE,
            video
          );
          gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
          requestAnimationFrame(render);
        } catch (err) {
          console.error('WebGL渲染错误:', err);
          animationStopped = true;
        }
      }
      render();

      // 输出美颜流
      let beautifiedStream: MediaStream;
      try {
        beautifiedStream = canvas.captureStream(25);
        // 保留原音轨
        originStream
          .getAudioTracks()
          .forEach(track => beautifiedStream.addTrack(track));
      } catch (err) {
        console.error('创建美颜流失败:', err);
        return originStream;
      }

      // 清理资源的函数
      const cleanup = () => {
        animationStopped = true;
        if (gl) {
          // 释放WebGL资源
          if (positionBuffer) gl.deleteBuffer(positionBuffer);
          if (texCoordBuffer) gl.deleteBuffer(texCoordBuffer);
          if (texture) gl.deleteTexture(texture);
          if (vertexShader) gl.deleteShader(vertexShader);
          if (fragmentShader) gl.deleteShader(fragmentShader);
          if (program) gl.deleteProgram(program);
        }
        // 停止原视频轨道
        video.srcObject = null;
      };

      // 在流的轨道结束时清理资源
      beautifiedStream.getTracks().forEach(track => {
        track.addEventListener('ended', cleanup);
      });

      return beautifiedStream;
    },
    []
  );

  // 3. 初始化媒体流，支持美颜开关和强度
  const initMediaStream = useCallback(async (): Promise<MediaStream> => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({
        video: true,
        audio: {
          echoCancellation: true,
          noiseSuppression: true,
          autoGainControl: true,
        },
      });
      let finalStream = stream;
      if (beautyEnabled) {
        finalStream = await startBeautyFilter(
          stream,
          whitenStrength,
          blurStrength
        );
      }
      userStreamRef.current = finalStream;
      if (userVideoRef.current) {
        userVideoRef.current.srcObject = finalStream;
      }
      return finalStream;
    } catch (err) {
      const errorMessage = '无法访问摄像头/麦克风，请检查权限设置';
      console.error(errorMessage, err);
      setError(errorMessage);
      throw err;
    }
  }, [startBeautyFilter, beautyEnabled, whitenStrength, blurStrength]);

  // 4. 监听美颜参数变化，动态切换美颜流
  useEffect(() => {
    (async () => {
      if (!userStreamRef.current) return;
      const tracks = userStreamRef.current.getTracks();
      const stream = await navigator.mediaDevices.getUserMedia({
        video: true,
        audio: {
          echoCancellation: true,
          noiseSuppression: true,
          autoGainControl: true,
        },
      });
      let finalStream = stream;
      if (beautyEnabled) {
        finalStream = await startBeautyFilter(
          stream,
          whitenStrength,
          blurStrength
        );
      }
      userStreamRef.current = finalStream;
      if (userVideoRef.current) {
        userVideoRef.current.srcObject = finalStream;
      }
      // 替换WebRTC视频轨道
      Object.values(peerConnectionsRef.current).forEach(pc => {
        const sender = pc
          .getSenders()
          .find(s => s.track && s.track.kind === 'video');
        if (sender) {
          const newTrack = finalStream.getVideoTracks()[0];
          if (newTrack) sender.replaceTrack(newTrack);
        }
      });
      // 停止旧流
      tracks.forEach(track => track.stop());
    })();
  }, [beautyEnabled, whitenStrength, blurStrength, startBeautyFilter]);

  // 初始化屏幕共享

  const initScreenShare = useCallback(async (): Promise<MediaStream> => {
    try {
      // 获取屏幕共享流
      const stream = await navigator.mediaDevices.getDisplayMedia({
        video: true,
        audio: true,
      });

      // 保存屏幕共享流的引用
      screenShareRef.current = stream;
      setScreenSharing(true);

      // 替换所有peer的流
      Object.values(peerConnectionsRef.current).forEach(pc => {
        try {
          const sender = pc.getSenders().find(s => s.track?.kind === 'video');
          if (sender && stream.getVideoTracks()[0]) {
            sender.replaceTrack(stream.getVideoTracks()[0]);
          }
        } catch (err) {
          console.error('替换视频轨道失败:', err);
        }
      });

      // 监听屏幕共享结束
      stream.getVideoTracks()[0].onended = () => {
        stopScreenShare();
      };

      return stream;
    } catch (err) {
      const errorMessage = '屏幕共享失败，可能是用户取消或权限问题';
      console.error(errorMessage, err);
      setError(errorMessage);
      throw err;
    }
  }, []);

  // 停止屏幕共享
  const stopScreenShare = useCallback((): void => {
    if (screenShareRef.current) {
      try {
        // 停止所有屏幕共享轨道
        screenShareRef.current.getTracks().forEach(track => {
          try {
            track.stop();
          } catch (err) {
            console.error('停止屏幕共享轨道失败:', err);
          }
        });

        screenShareRef.current = null;
        setScreenSharing(false);

        // 恢复摄像头视频流
        if (userStreamRef.current) {
          Object.values(peerConnectionsRef.current).forEach(pc => {
            try {
              const sender = pc
                .getSenders()
                .find(s => s.track?.kind === 'video');
              if (sender && userStreamRef.current?.getVideoTracks()[0]) {
                sender.replaceTrack(userStreamRef.current.getVideoTracks()[0]);
              }
            } catch (err) {
              console.error('恢复视频轨道失败:', err);
            }
          });
        }
      } catch (err) {
        console.error('停止屏幕共享时发生错误:', err);
      }
    }
  }, []);

  // 切换视频状态
  const toggleVideo = useCallback((): void => {
    if (userStreamRef.current) {
      const videoTrack = userStreamRef.current.getVideoTracks()[0];
      if (videoTrack) {
        videoTrack.enabled = !videoTrack.enabled;
        setVideoEnabled(videoTrack.enabled);
      }
    }
  }, []);

  // 切换音频状态
  const toggleAudio = useCallback((): void => {
    if (userStreamRef.current) {
      const audioTrack = userStreamRef.current.getAudioTracks()[0];
      if (audioTrack) {
        audioTrack.enabled = !audioTrack.enabled;
        setAudioEnabled(audioTrack.enabled);
      }
    }
  }, []);

  // 切换屏幕共享
  const toggleScreenShare = useCallback(async (): Promise<void> => {
    if (screenSharing) {
      stopScreenShare();
    } else {
      try {
        await initScreenShare();
      } catch (err) {
        console.error('屏幕共享失败:', err);
      }
    }
  }, [screenSharing, initScreenShare, stopScreenShare]);

  // 复制邀请链接
  const copyInviteLink = useCallback((): void => {
    const link = `https://${localIP}:5173/?room=${roomId}`;
    navigator.clipboard
      .writeText(link)
      .then(() => {
        setCopied(true);
        setTimeout(() => setCopied(false), 2000);
      })
      .catch(err => {
        console.error('复制链接失败:', err);
        setError('复制链接失败，请手动复制');
      });
  }, [localIP, roomId]);

  // 离开会议
  const leaveMeeting = useCallback((): void => {
    window.location.href = '/';
  }, []);

  // 添加/移除远程peer
  const addPeer = useCallback((peerId: string, stream: MediaStream): void => {
    setPeers(prev => {
      if (!prev.some(p => p.peerId === peerId)) {
        return [...prev, { peerId, stream }];
      }
      return prev.map(p => (p.peerId === peerId ? { ...p, stream } : p));
    });
  }, []);

  const removePeer = useCallback((peerId: string): void => {
    setPeers(prev => prev.filter(p => p.peerId !== peerId));
    if (peerConnectionsRef.current[peerId]) {
      peerConnectionsRef.current[peerId].close();
      delete peerConnectionsRef.current[peerId];
    }
    if (remoteVideoRefs.current[peerId]) {
      delete remoteVideoRefs.current[peerId];
    }
  }, []);

  // 1. 举手状态
  const [raiseHandUser, setRaiseHandUser] = useState<string | null>(null);
  const [showRaiseHand, setShowRaiseHand] = useState(false);

  // 2. 修改 createNativePeerConnection，添加 DataChannel
  const createNativePeerConnection = useCallback(
    (
      remoteUserId: string,
      localStream: MediaStream,
      socket: Socket,
      isInitiator: boolean
    ): RTCPeerConnection => {
      const pc = new RTCPeerConnection({
        iceServers: [
          { urls: 'stun:stun.l.google.com:19302' },
          { urls: 'stun:stun1.l.google.com:19302' },
          { urls: 'stun:stun2.l.google.com:19302' },
        ],
      });

      // 添加本地流
      localStream.getTracks().forEach(track => {
        pc.addTrack(track, localStream);
      });

      // DataChannel
      let dataChannel: RTCDataChannel | null = null;
      if (isInitiator) {
        dataChannel = pc.createDataChannel('signal');
        dataChannel.onopen = () => {
          console.error('DataChannel open');
        };
        dataChannel.onmessage = event => {
          const msg = JSON.parse(event.data);
          if (msg.type === 'raiseHand') {
            setRaiseHandUser(msg.userId);
            setShowRaiseHand(true);
            setTimeout(() => setShowRaiseHand(false), 3000);
          }
        };
        const extendedPc = pc as ExtendedRTCPeerConnection;
        extendedPc.dataChannels = extendedPc.dataChannels || {};
        if (extendedPc.dataChannels) {
          extendedPc.dataChannels[remoteUserId] = dataChannel;
        }
      }
      pc.ondatachannel = event => {
        const channel = event.channel;
        channel.onmessage = event => {
          const msg = JSON.parse(event.data);
          if (msg.type === 'raiseHand') {
            setRaiseHandUser(msg.userId);
            setShowRaiseHand(true);
            setTimeout(() => setShowRaiseHand(false), 3000);
          }
        };
        channel.onopen = () => {
          console.error('DataChannel open');
        };
        const extendedPc = pc as ExtendedRTCPeerConnection;
        extendedPc.dataChannels = extendedPc.dataChannels || {};
        if (extendedPc.dataChannels) {
          extendedPc.dataChannels[remoteUserId] = channel;
        }
      };

      // ICE候选处理
      pc.onicecandidate = event => {
        if (event.candidate) {
          socket.emit('signal', {
            recipientId: remoteUserId,
            signal: event.candidate,
          });
        }
      };

      // 远程流处理
      pc.ontrack = event => {
        const remoteStream = event.streams[0];
        if (remoteStream) {
          addPeer(remoteUserId, remoteStream);
        }
      };

      // 协商处理
      pc.onnegotiationneeded = async () => {
        if (isInitiator) {
          try {
            const offer = await pc.createOffer();
            await pc.setLocalDescription(offer);
            socket.emit('signal', {
              recipientId: remoteUserId,
              signal: pc.localDescription,
            });
          } catch (err) {
            console.error('创建offer失败:', err);
            setError('创建连接失败');
          }
        }
      };

      // 连接状态处理
      pc.oniceconnectionstatechange = () => {
        if (
          pc.iceConnectionState === 'disconnected' ||
          pc.iceConnectionState === 'failed' ||
          pc.iceConnectionState === 'closed'
        ) {
          removePeer(remoteUserId);
        }
      };

      peerConnectionsRef.current[remoteUserId] = pc;
      const extendedPc = pc as ExtendedRTCPeerConnection;
      extendedPc.dataChannels = extendedPc.dataChannels || {};
      return pc;
    },
    [addPeer, removePeer]
  );

  // WebRTC 连接的远程视频流处理
  useEffect(() => {
    peers.forEach(peer => {
      const videoElement = remoteVideoRefs.current[peer.peerId];
      if (
        videoElement &&
        peer.stream &&
        videoElement.srcObject !== peer.stream
      ) {
        videoElement.srcObject = peer.stream;
      }
    });
  }, [peers]);

  // 设置WebRTC处理器
  const setupWebRTCHandlers = useCallback(
    (socket: Socket, localStream: MediaStream): void => {
      socket.on('users-in-room', (users: string[]) => {
        setUsersInRoom(users);

        users.forEach((otherUserId: string) => {
          if (otherUserId !== userId) {
            const isInitiator = userId < otherUserId;
            if (!peerConnectionsRef.current[otherUserId]) {
              createNativePeerConnection(
                otherUserId,
                localStream,
                socket,
                isInitiator
              );
            }
          }
        });

        Object.keys(peerConnectionsRef.current).forEach(peerId => {
          if (!users.includes(peerId)) {
            removePeer(peerId);
          }
        });
      });

      socket.on('user-connected', (newUserId: string) => {
        if (newUserId !== userId) {
          const isInitiator = userId < newUserId;
          if (!peerConnectionsRef.current[newUserId]) {
            createNativePeerConnection(
              newUserId,
              localStream,
              socket,
              isInitiator
            );
          }
        }
      });

      socket.on('user-disconnected', (disconnectedUserId: string) => {
        removePeer(disconnectedUserId);
      });

      socket.on('signal', ({ senderId, signal }: SignalData) => {
        const pc = peerConnectionsRef.current[senderId];
        if (!pc) return;

        if (pc.signalingState !== 'closed') {
          try {
            if (
              'type' in signal &&
              (signal.type === 'offer' || signal.type === 'answer')
            ) {
              const isOffer = signal.type === 'offer';

              // 如果是offer，需要先设置远程描述
              if (isOffer) {
                pc.setRemoteDescription(new RTCSessionDescription(signal))
                  .then(() => pc.createAnswer())
                  .then(answer => pc.setLocalDescription(answer))
                  .then(() => {
                    if (pc.localDescription) {
                      socket.emit('signal', {
                        recipientId: senderId,
                        signal: pc.localDescription,
                      });
                    }
                  })
                  .catch(err => {
                    console.error('处理offer失败:', err);
                    // 如果处理失败，尝试重新创建连接
                    if (pc.signalingState === 'stable') {
                      pc.createOffer()
                        .then(offer => pc.setLocalDescription(offer))
                        .then(() => {
                          if (pc.localDescription) {
                            socket.emit('signal', {
                              recipientId: senderId,
                              signal: pc.localDescription,
                            });
                          }
                        })
                        .catch(err => console.error('重新创建offer失败:', err));
                    }
                  });
              } else {
                // 如果是answer，直接设置远程描述
                pc.setRemoteDescription(
                  new RTCSessionDescription(signal)
                ).catch(err => console.error('设置answer失败:', err));
              }
            } else if ('candidate' in signal) {
              pc.addIceCandidate(new RTCIceCandidate(signal)).catch(err =>
                console.error('添加ICE候选失败:', err)
              );
            }
          } catch (err) {
            console.error('处理信号失败:', err);
          }
        }
      });
    },
    [userId, createNativePeerConnection, removePeer]
  );

  // 初始化Socket连接

  useEffect(() => {
    let isMounted = true; // 用于防止组件卸载后的状态更新
    const serverUrl = getServerUrl();
    console.log('正在连接服务器:', serverUrl);

    const socket = io(serverUrl, {
      transports: ['websocket', 'polling'], // 添加polling作为备选传输方式
      reconnection: true,
      reconnectionAttempts: 5,
      reconnectionDelay: 1000,
      timeout: 5000,
      forceNew: true,
      autoConnect: true,
      path: '/socket.io', // 明确指定路径
      secure: true, // 启用安全连接
    });

    socket.on('connect', () => {
      console.log('WebSocket连接成功');
    });

    socket.on('connect_error', error => {
      console.error('WebSocket连接失败:', error);
      if (isMounted) {
        setError(`连接服务器失败: ${error.message}
        请检查:
        1. 后端服务器是否已启动（端口3000）
        2. 服务器地址是否正确: ${serverUrl}
        3. 防火墙是否允许WebSocket连接
        4. 网络连接是否正常
        5. HTTPS证书是否有效`);
      }
    });

    socketRef.current = socket;

    const handleConnect = async () => {
      console.error('连接服务器成功');
      try {
        const stream = await initMediaStream();
        if (!isMounted) {
          // 如果组件已卸载，清理资源并返回
          stream.getTracks().forEach(track => track.stop());
          return;
        }

        userStreamRef.current = stream;
        if (userVideoRef.current) {
          userVideoRef.current.srcObject = stream;
        }
        socket.emit('join-room', roomId, userId, userName);
        setupWebRTCHandlers(socket, stream);
      } catch (err) {
        console.error('获取媒体流失败:', err);
        if (isMounted) {
          setError('无法访问摄像头/麦克风');
        }
      }
    };

    socket.on('connect', handleConnect);

    socket.on('chat-history', (history: ChatMessage[]) => {
      if (isMounted) {
        setChatMessages(history);
        scrollToBottom();
      }
    });

    socket.on('chat-message', (message: ChatMessage) => {
      if (isMounted) {
        setChatMessages(prev => [...prev, message]);
      }
    });

    // 清理函数
    return () => {
      isMounted = false;

      if (socketRef.current) {
        // 明确移除所有事件监听器
        socket.off('connect');
        socket.off('connect_error');
        socket.off('users-in-room');
        socket.off('user-connected');
        socket.off('user-disconnected');
        socket.off('signal');
        socket.off('chat-history');
        socket.off('chat-message');
        socket.off('whiteboard-state');
        socket.off('whiteboard-history');
        socket.off('whiteboard-update');
        socket.off('whiteboard-clear');
        socket.off('flower-counts');

        // 通知服务器离开房间
        socketRef.current.emit('leave-room', roomId, userId);
        socketRef.current.disconnect();
      }

      // 停止所有媒体轨道
      if (userStreamRef.current) {
        userStreamRef.current.getTracks().forEach(track => track.stop());
      }

      if (screenShareRef.current) {
        screenShareRef.current.getTracks().forEach(track => track.stop());
      }

      // 关闭所有对等连接
      Object.values(peerConnectionsRef.current).forEach(pc => {
        try {
          pc.close();
        } catch (err) {
          console.error('关闭对等连接失败:', err);
        }
      });

      // 重置连接引用
      peerConnectionsRef.current = {};
      setPeers([]);
    };
  }, [
    roomId,
    userId,
    userName,
    getServerUrl,
    initMediaStream,
    setupWebRTCHandlers,
  ]);

  // 自动滚动到最新消息
  const scrollToBottom = useCallback((): void => {
    if (chatContainerRef.current) {
      chatContainerRef.current.scrollTop =
        chatContainerRef.current.scrollHeight;
    }
  }, []);

  // 聊天未读消息数逻辑

  useEffect(() => {
    // 只要有新消息且聊天窗口未打开，未读数递增
    if (!showChat && chatMessages.length > 0) {
      setUnreadCount(prev => prev + 1);
    }
    // 聊天窗口打开时未读数归零
    if (showChat) {
      setUnreadCount(0);
      scrollToBottom();
    }
  }, [chatMessages, showChat, scrollToBottom]);

  // 发送聊天消息
  const sendMessage = useCallback(
    (e: React.FormEvent<HTMLFormElement>): void => {
      e.preventDefault();
      if (newMessage.trim() && socketRef.current) {
        socketRef.current.emit('chat-message', newMessage);
        setNewMessage('');
        setShowEmojiPicker(false); // 发送消息时关闭表情选择器
      }
    },
    [newMessage]
  );

  // 处理点击外部关闭emoji选择器
  useEffect(() => {
    const handleClickOutside = (event: MouseEvent | TouchEvent) => {
      if (
        emojiPickerRef.current &&
        !emojiPickerRef.current.contains(event.target as Node) &&
        !(event.target as Element).closest('.emoji-button')
      ) {
        setShowEmojiPicker(false);
      }
    };

    document.addEventListener('mousedown', handleClickOutside);
    document.addEventListener('touchstart', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
      document.removeEventListener('touchstart', handleClickOutside);
    };
  }, []);

  // 处理表情点击
  const handleEmojiClick = useCallback((emojiData: EmojiClickData) => {
    setNewMessage(prev => prev + emojiData.emoji);
    // 不立即关闭，允许连续选择表情
  }, []);

  // 格式化时间
  const formatTime = useCallback((timestamp: number): string => {
    return new Date(timestamp).toLocaleTimeString();
  }, []);

  // 聊天消息渲染图片
  const renderMessage = useCallback(
    (msg: ChatMessage): React.ReactElement | null => {
      switch (msg.type) {
        case 'system':
          return (
            <div className="system-message">
              <span className="message-time">
                {formatTime(msg.timestamp as number)}
              </span>
              <span className="message-content">
                {typeof msg.message === 'string'
                  ? msg.message
                  : '[不支持的消息类型]'}
              </span>
            </div>
          );
        case 'user':
          return (
            <div
              className={`chat-message ${msg.userId === userId ? 'own-message' : ''}`}
            >
              <div className="message-header">
                <span className="message-sender">
                  {msg.userName || msg.userId}
                </span>
                <span className="message-time">
                  {formatTime(msg.timestamp as number)}
                </span>
              </div>
              <div className="message-content">
                {typeof msg.message === 'string'
                  ? msg.message
                  : '[不支持的消息类型]'}
              </div>
            </div>
          );
        default:
          return null;
      }
    },
    [userId, formatTime]
  );

  // 处理远程白板更新
  const handleWhiteboardUpdate = useCallback((action: WhiteboardAction) => {
    console.error('处理白板更新:', action);
    if (!contextRef.current) {
      console.error('白板上下文不存在');
      return;
    }

    try {
      if (action.action === 'draw' && action.data) {
        const { x, y, type, color, lineWidth } = action.data;
        console.error(
          `处理绘制动作: ${type}, 位置: (${x}, ${y}), 颜色: ${color}, 线宽: ${lineWidth}`
        );

        // 设置远程用户的绘制样式
        contextRef.current.strokeStyle = color;
        contextRef.current.lineWidth = lineWidth;

        if (type === 'start') {
          contextRef.current.beginPath();
          contextRef.current.moveTo(x, y);
        } else if (type === 'move') {
          contextRef.current.lineTo(x, y);
          contextRef.current.stroke();
        } else if (type === 'end') {
          contextRef.current.closePath();
        }
      } else if (action.action === 'clear') {
        console.error('清除白板');
        if (canvasRef.current) {
          contextRef.current.clearRect(
            0,
            0,
            canvasRef.current.width,
            canvasRef.current.height
          );
        }
      }
    } catch (error) {
      console.error('处理白板更新时出错:', error);
    }
  }, []);

  // 切换白板显示状态（只发 socket 事件，不本地 setShowWhiteboard）
  const toggleWhiteboard = useCallback(() => {
    const newState = !showWhiteboard;
    setShowWhiteboard(newState); // 本地立即更新状态

    // 通知其他用户
    if (socketRef.current) {
      socketRef.current.emit('whiteboard-visibility-change', {
        roomId,
        isVisible: newState,
      });
    }

    // 如果是打开白板，请求历史数据
    if (newState && socketRef.current) {
      socketRef.current.emit('whiteboard-request-history', roomId);
    }
  }, [showWhiteboard, roomId]);

  // 监听白板事件（只用 socket 事件 setShowWhiteboard）
  useEffect(() => {
    if (socketRef.current) {
      socketRef.current.on(
        'whiteboard-state',
        (state: { isVisible: boolean }) => {
          // 当其他用户改变白板状态时，同步本地状态
          setShowWhiteboard(state.isVisible);
        }
      );

      // 修复whiteboard-history事件处理
      socketRef.current.on(
        'whiteboard-history',
        (history: WhiteboardAction[]) => {
          console.error('收到白板历史数据:', history.length, '条记录');
          // 重放历史绘制
          if (contextRef.current) {
            history.forEach(action => {
              try {
                handleWhiteboardUpdate(action);
              } catch (error) {
                console.error('重放历史绘制失败:', error);
              }
            });
          }
        }
      );

      socketRef.current.on('whiteboard-update', (action: WhiteboardAction) => {
        console.error('收到白板更新事件:', action);
        if (contextRef.current) {
          try {
            // 无论是谁发送的绘制事件，都在本地处理
            handleWhiteboardUpdate(action);
          } catch (error) {
            console.error('处理白板更新失败:', error);
          }
        }
      });

      socketRef.current.on('whiteboard-clear', () => {
        console.error('收到白板清除事件');
        if (contextRef.current && canvasRef.current) {
          try {
            contextRef.current.clearRect(
              0,
              0,
              canvasRef.current.width,
              canvasRef.current.height
            );
          } catch (error) {
            console.error('清除白板失败:', error);
          }
        }
      });

      // 打开白板时请求历史数据
      if (showWhiteboard && socketRef.current) {
        console.error('请求白板历史数据');
        socketRef.current.emit('whiteboard-request-history', roomId);
      }
    }

    return () => {
      if (socketRef.current) {
        socketRef.current.off('whiteboard-state');
        socketRef.current.off('whiteboard-history');
        socketRef.current.off('whiteboard-update');
        socketRef.current.off('whiteboard-clear');
      }
    };
  }, [handleWhiteboardUpdate, showWhiteboard, roomId]);

  // 每当白板显示状态改变时，请求历史数据
  useEffect(() => {
    if (showWhiteboard && socketRef.current) {
      console.error('白板显示状态改变，请求历史数据');
      socketRef.current.emit('whiteboard-request-history', roomId);
    }
  }, [showWhiteboard, roomId]);

  // 初始化白板
  const initWhiteboard = useCallback(() => {
    console.error('初始化白板');
    const canvas = canvasRef.current;
    if (!canvas) {
      console.error('找不到画布元素');
      return () => {}; // 返回一个空函数，表示没有清理
    }

    canvas.width = canvas.offsetWidth;
    canvas.height = canvas.offsetHeight;

    const context = canvas.getContext('2d');
    if (!context) {
      console.error('无法获取画布上下文');
      return () => {}; // 返回一个空函数，表示没有清理
    }

    context.lineCap = 'round';
    context.lineJoin = 'round';
    context.strokeStyle = currentColor;
    context.lineWidth = lineWidth;
    contextRef.current = context;

    // 添加原生触摸事件监听器，使用 {passive: false} 选项
    const handleTouchStart = (e: TouchEvent) => {
      e.preventDefault(); // 在原生事件中可以安全地使用 preventDefault
      if (!contextRef.current || !canvasRef.current) return;

      const touch = e.touches[0];
      const rect = canvas.getBoundingClientRect();
      const offsetX = touch.clientX - rect.left;
      const offsetY = touch.clientY - rect.top;

      // 构建绘制数据
      const drawData = {
        roomId,
        userId, // 添加用户ID，标识是谁发送的
        action: 'draw',
        data: {
          x: offsetX,
          y: offsetY,
          type: 'start',
          color: currentColor,
          lineWidth,
        },
      };

      // 本地绘制
      contextRef.current.strokeStyle = currentColor;
      contextRef.current.lineWidth = lineWidth;
      contextRef.current.beginPath();
      contextRef.current.moveTo(offsetX, offsetY);
      setIsDrawing(true);

      // 发送绘制事件到服务器
      if (socketRef.current) {
        console.error('发送绘制开始事件:', drawData);
        socketRef.current.emit('whiteboard-draw', drawData);
      }
    };

    const handleTouchMove = (e: TouchEvent) => {
      e.preventDefault();
      if (!isDrawing || !contextRef.current || !canvasRef.current) return;

      const touch = e.touches[0];
      const rect = canvas.getBoundingClientRect();
      const offsetX = touch.clientX - rect.left;
      const offsetY = touch.clientY - rect.top;

      // 构建绘制数据
      const drawData = {
        roomId,
        userId, // 添加用户ID
        action: 'draw',
        data: {
          x: offsetX,
          y: offsetY,
          type: 'move',
          color: currentColor,
          lineWidth,
        },
      };

      // 本地绘制
      contextRef.current.strokeStyle = currentColor;
      contextRef.current.lineWidth = lineWidth;
      contextRef.current.lineTo(offsetX, offsetY);
      contextRef.current.stroke();

      // 发送绘制事件到服务器
      if (socketRef.current) {
        socketRef.current.emit('whiteboard-draw', drawData);
      }
    };

    const handleTouchEnd = (e: TouchEvent) => {
      e.preventDefault();
      if (!contextRef.current) return;

      // 构建绘制数据
      const drawData = {
        roomId,
        userId, // 添加用户ID，标识是谁发送的
        action: 'draw',
        data: {
          x: 0,
          y: 0,
          type: 'end',
          color: currentColor,
          lineWidth,
        },
      };

      // 本地绘制结束
      contextRef.current.closePath();
      setIsDrawing(false);

      // 发送绘制结束事件到服务器
      if (socketRef.current) {
        console.error('发送绘制结束事件:', drawData);
        socketRef.current.emit('whiteboard-draw', drawData);
      }
    };

    // 添加事件监听器
    canvas.addEventListener('touchstart', handleTouchStart, { passive: false });
    canvas.addEventListener('touchmove', handleTouchMove, { passive: false });
    canvas.addEventListener('touchend', handleTouchEnd, { passive: false });
    canvas.addEventListener('touchcancel', handleTouchEnd, { passive: false });

    // 返回清理函数，在组件卸载时移除事件监听器
    return () => {
      canvas.removeEventListener('touchstart', handleTouchStart);
      canvas.removeEventListener('touchmove', handleTouchMove);
      canvas.removeEventListener('touchend', handleTouchEnd);
      canvas.removeEventListener('touchcancel', handleTouchEnd);
    };

    console.error('白板初始化完成');
  }, [currentColor, lineWidth, isDrawing, roomId, userId]);

  // 开始绘制 - 鼠标事件
  const startDrawing = useCallback(
    ({ nativeEvent }: React.MouseEvent<HTMLCanvasElement>) => {
      const { offsetX, offsetY } = nativeEvent;
      if (!contextRef.current) {
        console.error('白板上下文不存在');
        return;
      }

      console.error('开始绘制:', offsetX, offsetY);

      // 构建绘制数据
      const drawData = {
        roomId,
        userId, // 添加用户ID，标识是谁发送的
        action: 'draw',
        data: {
          x: offsetX,
          y: offsetY,
          type: 'start',
          color: currentColor,
          lineWidth,
        },
      };

      // 本地绘制
      contextRef.current.strokeStyle = currentColor;
      contextRef.current.lineWidth = lineWidth;
      contextRef.current.beginPath();
      contextRef.current.moveTo(offsetX, offsetY);
      setIsDrawing(true);

      // 发送绘制事件到服务器
      if (socketRef.current) {
        console.error('发送绘制开始事件:', drawData);
        socketRef.current.emit('whiteboard-draw', drawData);
      }
    },
    [roomId, userId, currentColor, lineWidth]
  );

  // 绘制中 - 鼠标事件
  const draw = useCallback(
    ({ nativeEvent }: React.MouseEvent<HTMLCanvasElement>) => {
      if (!isDrawing || !contextRef.current) return;

      const { offsetX, offsetY } = nativeEvent;

      // 构建绘制数据
      const drawData = {
        roomId,
        userId, // 添加用户ID，标识是谁发送的
        action: 'draw',
        data: {
          x: offsetX,
          y: offsetY,
          type: 'move',
          color: currentColor,
          lineWidth,
        },
      };

      // 本地绘制
      contextRef.current.strokeStyle = currentColor;
      contextRef.current.lineWidth = lineWidth;
      contextRef.current.lineTo(offsetX, offsetY);
      contextRef.current.stroke();

      // 发送绘制事件到服务器
      if (socketRef.current) {
        socketRef.current.emit('whiteboard-draw', drawData);
      }
    },
    [isDrawing, roomId, userId, currentColor, lineWidth]
  );

  // 结束绘制 - 鼠标事件
  const finishDrawing = useCallback(() => {
    if (!contextRef.current) return;
    console.error('结束绘制');

    // 构建绘制数据
    const drawData = {
      roomId,
      userId, // 添加用户ID，标识是谁发送的
      action: 'draw',
      data: {
        x: 0,
        y: 0,
        type: 'end',
        color: currentColor,
        lineWidth,
      },
    };

    // 本地绘制结束
    contextRef.current.closePath();
    setIsDrawing(false);

    // 发送绘制结束事件到服务器
    if (socketRef.current) {
      console.error('发送绘制结束事件:', drawData);
      socketRef.current.emit('whiteboard-draw', drawData);
    }
  }, [roomId, userId, currentColor, lineWidth]);

  // 开始绘制 - 触摸事件
  const startDrawingTouch = useCallback(
    (e: React.TouchEvent<HTMLCanvasElement>) => {
      // 不再调用 preventDefault，因为在 React 的合成事件中这会导致警告
      if (!contextRef.current || !canvasRef.current) return;

      const touch = e.touches[0];
      const canvas = canvasRef.current;
      const rect = canvas.getBoundingClientRect();
      const offsetX = touch.clientX - rect.left;
      const offsetY = touch.clientY - rect.top;

      // 构建绘制数据
      const drawData = {
        roomId,
        userId, // 添加用户ID，标识是谁发送的
        action: 'draw',
        data: {
          x: offsetX,
          y: offsetY,
          type: 'start',
          color: currentColor,
          lineWidth,
        },
      };

      // 本地绘制
      contextRef.current.strokeStyle = currentColor;
      contextRef.current.lineWidth = lineWidth;
      contextRef.current.beginPath();
      contextRef.current.moveTo(offsetX, offsetY);
      setIsDrawing(true);

      // 发送绘制事件到服务器
      if (socketRef.current) {
        socketRef.current.emit('whiteboard-draw', drawData);
      }
    },
    [roomId, userId, currentColor, lineWidth]
  );

  // 绘制中 - 触摸事件
  const drawTouch = useCallback(
    (e: React.TouchEvent<HTMLCanvasElement>) => {
      // 不再调用 preventDefault，因为在 React 的合成事件中这会导致警告
      if (!isDrawing || !contextRef.current || !canvasRef.current) return;

      const touch = e.touches[0];
      const canvas = canvasRef.current;
      const rect = canvas.getBoundingClientRect();
      const offsetX = touch.clientX - rect.left;
      const offsetY = touch.clientY - rect.top;

      // 构建绘制数据
      const drawData = {
        roomId,
        userId, // 添加用户ID，标识是谁发送的
        action: 'draw',
        data: {
          x: offsetX,
          y: offsetY,
          type: 'move',
          color: currentColor,
          lineWidth,
        },
      };

      // 本地绘制
      contextRef.current.strokeStyle = currentColor;
      contextRef.current.lineWidth = lineWidth;
      contextRef.current.lineTo(offsetX, offsetY);
      contextRef.current.stroke();

      // 发送绘制事件到服务器
      if (socketRef.current) {
        socketRef.current.emit('whiteboard-draw', drawData);
      }
    },
    [isDrawing, roomId, userId, currentColor, lineWidth]
  );

  // 结束绘制 - 触摸事件
  const finishDrawingTouch = useCallback(
    (e: React.TouchEvent<HTMLCanvasElement>) => {
      // 不再调用 preventDefault，因为在 React 的合成事件中这会导致警告
      if (!contextRef.current) return;

      // 构建绘制数据
      const drawData = {
        roomId,
        userId, // 添加用户ID，标识是谁发送的
        action: 'draw',
        data: {
          x: 0,
          y: 0,
          type: 'end',
          color: currentColor,
          lineWidth,
        },
      };

      // 本地绘制结束
      contextRef.current.closePath();
      setIsDrawing(false);

      // 发送绘制结束事件到服务器
      if (socketRef.current) {
        socketRef.current.emit('whiteboard-draw', drawData);
      }
    },
    [roomId, userId, currentColor, lineWidth]
  );

  // 清除白板
  const clearWhiteboard = useCallback(() => {
    console.error('清除白板');
    if (!contextRef.current || !canvasRef.current) return;
    contextRef.current.clearRect(
      0,
      0,
      canvasRef.current.width,
      canvasRef.current.height
    );

    if (socketRef.current) {
      console.error('发送清除白板事件');
      socketRef.current.emit('whiteboard-clear', roomId);
    }
  }, [roomId]);

  // 初始化白板
  useEffect(() => {
    if (showWhiteboard) {
      const cleanup = initWhiteboard();
      return () => {
        if (cleanup) cleanup();
      };
    }
  }, [showWhiteboard, initWhiteboard]);

  // 语音激励（说话者检测）相关状态
  const [speakingUsers, setSpeakingUsers] = useState<{
    [userId: string]: boolean;
  }>({});

  // 本地说话检测
  useEffect(() => {
    if (!userStreamRef.current) return;
    let audioContext: AudioContext | null = null;
    let analyser: AnalyserNode | null = null;
    let source: MediaStreamAudioSourceNode | null = null;

    try {
      audioContext = new (window.AudioContext || window.webkitAudioContext)();
      source = audioContext.createMediaStreamSource(userStreamRef.current);
      analyser = audioContext.createAnalyser();
      analyser.fftSize = 512;
      source.connect(analyser);
    } catch (err) {
      console.error('创建音频分析器失败:', err);
      return () => {};
    }

    let stopped = false;
    function getVolume() {
      if (!analyser) return 0;
      const data = new Uint8Array(analyser.fftSize);
      analyser.getByteTimeDomainData(data);
      let sum = 0;
      for (let i = 0; i < data.length; i++) {
        const val = (data[i] - 128) / 128;
        sum += val * val;
      }
      return Math.sqrt(sum / data.length);
    }
    function detect() {
      if (stopped) return;
      const vol = getVolume();
      setSpeakingUsers(prev => ({ ...prev, [userId]: vol > 0.05 }));
      setTimeout(detect, 200);
    }
    detect();
    return () => {
      stopped = true;
      if (source) source.disconnect();
      if (audioContext) audioContext.close();
    };
  }, [userId]);

  // 远程说话检测
  useEffect(() => {
    const remoteAudioContexts: { [peerId: string]: AudioContext } = {};
    const remoteAnalysers: { [peerId: string]: AnalyserNode } = {};
    const remoteSources: { [peerId: string]: MediaStreamAudioSourceNode } = {};
    let stopped = false;

    try {
      peers.forEach(peer => {
        if (peer.stream) {
          const ctx = new (window.AudioContext || window.webkitAudioContext)();
          const src = ctx.createMediaStreamSource(peer.stream);
          const analyser = ctx.createAnalyser();
          analyser.fftSize = 512;
          src.connect(analyser);
          remoteAudioContexts[peer.peerId] = ctx;
          remoteAnalysers[peer.peerId] = analyser;
          remoteSources[peer.peerId] = src;
        }
      });
    } catch (err) {
      console.error('创建远程音频分析器失败:', err);
      return () => {};
    }

    function getVolume(analyser: AnalyserNode) {
      const data = new Uint8Array(analyser.fftSize);
      analyser.getByteTimeDomainData(data);
      let sum = 0;
      for (let i = 0; i < data.length; i++) {
        const val = (data[i] - 128) / 128;
        sum += val * val;
      }
      return Math.sqrt(sum / data.length);
    }
    function detect() {
      if (stopped) return;
      const newSpeaking: { [userId: string]: boolean } = {};
      Object.entries(remoteAnalysers).forEach(([peerId, analyser]) => {
        const vol = getVolume(analyser);
        newSpeaking[peerId] = vol > 0.05;
      });
      setSpeakingUsers(prev => ({ ...prev, ...newSpeaking }));
      setTimeout(detect, 200);
    }
    detect();
    return () => {
      stopped = true;
      // Clean up sources first
      Object.values(remoteSources).forEach(src => {
        try {
          src.disconnect();
        } catch (err) {
          console.error('清理音频源失败:', err);
        }
      });
      // Then close contexts
      Object.values(remoteAudioContexts).forEach(ctx => {
        try {
          ctx.close();
        } catch (err) {
          console.error('关闭音频上下文失败:', err);
        }
      });
    };
  }, [peers]);

  // 鲜花系统功能函数
  const sendFlower = useCallback(
    (toUserId: string) => {
      if (socketRef.current && toUserId !== userId) {
        socketRef.current.emit('send-flower', {
          roomId,
          fromUserId: userId,
          fromUserName: userName || userId,
          toUserId,
        });

        // 触发鲜花动画
        setFlowerAnimation(prev => ({ ...prev, [toUserId]: true }));
        setTimeout(() => {
          setFlowerAnimation(prev => ({ ...prev, [toUserId]: false }));
        }, 2000);

        setShowFlowerPanel(false);
        setSelectedUserForFlower(null);
      }
    },
    [roomId, userId, userName]
  );

  const openFlowerPanel = useCallback((targetUserId: string) => {
    setSelectedUserForFlower(targetUserId);
    setShowFlowerPanel(true);
  }, []);

  // 视频录制功能
  const startRecording = useCallback(async () => {
    try {
      if (!userStreamRef.current) {
        console.error('没有可用的媒体流');
        return;
      }

      const mediaRecorder = new MediaRecorder(userStreamRef.current, {
        mimeType: 'video/webm;codecs=vp8,opus',
      });

      mediaRecorderRef.current = mediaRecorder;
      recordingStartTimeRef.current = Date.now();

      const chunks: Blob[] = [];

      mediaRecorder.ondataavailable = event => {
        if (event.data.size > 0) {
          chunks.push(event.data);
        }
      };

      mediaRecorder.onstop = () => {
        const blob = new Blob(chunks, { type: 'video/webm' });
        setRecordedBlobs(prev => [...prev, blob]);
        console.log('录制完成，视频大小:', blob.size);
      };

      mediaRecorder.start(1000); // 每秒收集一次数据
      setIsRecording(true);
      console.log('开始录制视频');
    } catch (error) {
      console.error('开始录制失败:', error);
      setError('录制失败，请检查浏览器支持');
    }
  }, []);

  const stopRecording = useCallback(() => {
    if (
      mediaRecorderRef.current &&
      mediaRecorderRef.current.state === 'recording'
    ) {
      mediaRecorderRef.current.stop();
      setIsRecording(false);
      console.log('停止录制视频');
    }
  }, []);

  const toggleRecording = useCallback(() => {
    if (isRecording) {
      stopRecording();
    } else {
      startRecording();
    }
  }, [isRecording, startRecording, stopRecording]);

  // 视频回放功能
  const startReplay = useCallback(() => {
    if (recordedBlobs.length === 0) {
      setError('没有可回放的视频');
      return;
    }

    // 合并所有录制的blob
    const combinedBlob = new Blob(recordedBlobs, { type: 'video/webm' });
    const videoUrl = URL.createObjectURL(combinedBlob);
    setReplayVideoUrl(videoUrl);
    setShowReplay(true);
  }, [recordedBlobs]);

  const toggleReplay = useCallback(() => {
    if (showReplay) {
      setShowReplay(false);
      setIsReplayPlaying(false);
      if (replayVideoUrl) {
        URL.revokeObjectURL(replayVideoUrl);
        setReplayVideoUrl(null);
      }
    } else {
      startReplay();
    }
  }, [showReplay, replayVideoUrl, startReplay]);

  const handleReplayPlayPause = useCallback(() => {
    if (replayVideoRef.current) {
      if (isReplayPlaying) {
        replayVideoRef.current.pause();
        setIsReplayPlaying(false);
      } else {
        replayVideoRef.current.play();
        setIsReplayPlaying(true);
      }
    }
  }, [isReplayPlaying]);

  const handleReplayProgress = useCallback(() => {
    if (replayVideoRef.current) {
      const progress =
        (replayVideoRef.current.currentTime / replayVideoRef.current.duration) *
        100;
      setReplayProgress(progress);
    }
  }, []);

  const handleReplaySeek = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      if (replayVideoRef.current) {
        const seekTime =
          (parseFloat(e.target.value) / 100) * replayVideoRef.current.duration;
        replayVideoRef.current.currentTime = seekTime;
      }
    },
    []
  );

  const downloadReplay = useCallback(() => {
    if (recordedBlobs.length === 0) return;

    const combinedBlob = new Blob(recordedBlobs, { type: 'video/webm' });
    const url = URL.createObjectURL(combinedBlob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `meeting-replay-${roomId}-${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.webm`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }, [recordedBlobs, roomId]);

  // 监听鲜花数量更新
  useEffect(() => {
    if (socketRef.current) {
      socketRef.current.on(
        'flower-counts',
        (counts: { [userId: string]: number }) => {
          setFlowerCounts(prev => {
            // 检查哪些用户的鲜花数量发生了变化
            const updatedUsers: { [userId: string]: boolean } = {};
            Object.keys(counts).forEach(userId => {
              if (counts[userId] !== prev[userId]) {
                updatedUsers[userId] = true;
              }
            });

            // 触发数量变化动画
            if (Object.keys(updatedUsers).length > 0) {
              setTimeout(() => {
                setFlowerAnimation(prev => ({ ...prev, ...updatedUsers }));
              }, 100);
            }

            return counts;
          });
        }
      );
    }

    return () => {
      if (socketRef.current) {
        socketRef.current.off('flower-counts');
      }
    };
  }, []);

  // 隐藏底部导航栏
  useEffect(() => {
    // 隐藏底部导航栏
    const tabBar = document.querySelector('.adm-tab-bar');
    if (tabBar) {
      tabBar.setAttribute('style', 'display: none !important');
    }

    // 组件卸载时恢复底部导航栏
    return () => {
      const tabBar = document.querySelector('.adm-tab-bar');
      if (tabBar) {
        tabBar.removeAttribute('style');
      }
    };
  }, []);

  return (
    <div className="meeting-room" style={{ backgroundColor: '#ffffff' }}>
      {error && (
        <div className="error-message">
          {error}
          <button onClick={() => setError(null)}>×</button>
        </div>
      )}
      {/* 视频区 */}
      <div className="video-container" style={{ backgroundColor: '#ffffff' }}>
        <div
          className={`user-video ${screenSharing ? 'screen-sharing' : ''} ${speakingUsers[userId] ? 'speaking' : ''}`}
        >
          <video
            ref={userVideoRef}
            autoPlay
            muted
            playsInline
            className={!videoEnabled ? 'video-disabled' : ''}
          />
          <div className="user-name">
            你 ({userId}) {screenSharing && '(屏幕共享中)'}
            {speakingUsers[userId] && (
              <span className="speaking-indicator">•</span>
            )}
          </div>
          {/* 鲜花显示 */}
          <div className="flower-display">
            <HeartOutlined style={{ color: '#ff6b6b', marginRight: 4 }} />
            <span>{flowerCounts[userId] || 0}</span>
          </div>
        </div>
        {peers.map(peer => (
          <div
            className={`peer-video ${speakingUsers[peer.peerId] ? 'speaking' : ''}`}
            key={peer.peerId}
          >
            <video
              ref={(el: HTMLVideoElement | null) => {
                if (el) {
                  remoteVideoRefs.current[peer.peerId] = el;
                }
              }}
              autoPlay
              playsInline
            />
            <div className="user-name">
              用户 {peer.peerId}
              {speakingUsers[peer.peerId] && (
                <span className="speaking-indicator">•</span>
              )}
            </div>
            {/* 鲜花显示和送花按钮 */}
            <div className="flower-display">
              <HeartOutlined style={{ color: '#ff6b6b', marginRight: 4 }} />
              <span>{flowerCounts[peer.peerId] || 0}</span>
              <button
                onClick={() => sendFlower(peer.peerId)}
                className="send-flower-button"
                title="送花"
              >
                <HeartOutlined style={{ color: '#ff6b6b' }} />
              </button>
            </div>
            {/* 鲜花动画 */}
            {flowerAnimation[peer.peerId] && (
              <div className="flower-animation">🌸</div>
            )}
          </div>
        ))}
      </div>

      {/* 控制栏 - 更适合移动设备的布局 */}
      <div className="controls">
        {/* 主要控制按钮组 */}
        <div className="controls-group">
          <button
            onClick={toggleAudio}
            className={!audioEnabled ? 'disabled' : ''}
            title={audioEnabled ? '静音' : '取消静音'}
          >
            {audioEnabled ? <AudioOutlined /> : <AudioMutedOutlined />}
          </button>
          <button
            onClick={toggleVideo}
            className={!videoEnabled ? 'disabled' : ''}
            title={videoEnabled ? '关闭视频' : '开启视频'}
          >
            {videoEnabled ? (
              <VideoCameraOutlined />
            ) : (
              <VideoCameraAddOutlined />
            )}
          </button>
          <button
            onClick={toggleScreenShare}
            className={screenSharing ? 'active' : ''}
            title={screenSharing ? '停止共享' : '共享屏幕'}
          >
            {screenSharing ? <CloseCircleOutlined /> : <DesktopOutlined />}
          </button>
          <button className="leave-btn" onClick={leaveMeeting} title="离开会议">
            <PhoneOutlined />
          </button>
        </div>

        {/* 功能按钮组 */}
        <div className="controls-group">
          <button
            onClick={() => setShowParticipants(!showParticipants)}
            className={showParticipants ? 'active' : ''}
            title="参会人员"
          >
            <TeamOutlined />
          </button>
          <button
            onClick={() => setShowChat(!showChat)}
            className={`control-button ${showChat ? 'active' : ''}`}
            title="聊天"
            style={{ position: 'relative' }}
          >
            <MessageOutlined />
            {unreadCount > 0 && !showChat && (
              <span className="unread-badge">{unreadCount}</span>
            )}
          </button>
          <button
            onClick={toggleWhiteboard}
            className={`control-button ${showWhiteboard ? 'active' : ''}`}
            title="白板"
          >
            <MdBrush />
          </button>
          <button
            onClick={() => {
              setShowTranscript(!showTranscript);
              // 当显示会议纪要时，隐藏其他可能冲突的组件
              if (!showTranscript) {
                setShowChat(false);
                setShowWhiteboard(false);
                setShowEmojiPicker(false);
              }
            }}
            className={`control-button ${showTranscript ? 'active' : ''} ${isTranscriptRecording ? 'recording' : ''}`}
            title={isTranscriptRecording ? '会议纪要 (录音中)' : '会议纪要'}
            style={{ position: 'relative' }}
          >
            📝
            {isTranscriptRecording && (
              <span className="recording-indicator">●</span>
            )}
          </button>
          <button
            onClick={copyInviteLink}
            className={copied ? 'copied' : ''}
            title="复制邀请链接"
          >
            <CopyOutlined />
            {copied && <span className="copied-text">已复制!</span>}
          </button>
        </div>

        {/* 辅助功能按钮组 */}
        <div className="controls-group">
          <button
            onClick={() => setBeautyEnabled(v => !v)}
            className={beautyEnabled ? 'active' : ''}
            title={beautyEnabled ? '关闭美颜' : '开启美颜'}
          >
            <StarOutlined />
          </button>
          <button
            onClick={() => {
              Object.values(peerConnectionsRef.current).forEach(pc => {
                const extendedPc = pc as ExtendedRTCPeerConnection;
                const channels = extendedPc.dataChannels
                  ? Object.values(extendedPc.dataChannels)
                  : [];
                channels.forEach((channel: RTCDataChannel) => {
                  if (channel.readyState === 'open') {
                    channel.send(JSON.stringify({ type: 'raiseHand', userId }));
                  }
                });
              });
            }}
            title="举手"
          >
            <RiseOutlined />
          </button>
          <button
            onClick={toggleRecording}
            className={`control-button ${isRecording ? 'recording' : ''}`}
            title={isRecording ? '停止录制' : '开始录制'}
            style={{ position: 'relative' }}
          >
            {isRecording ? <PauseCircleOutlined /> : <PlayCircleOutlined />}
            {isRecording && <span className="recording-indicator">●</span>}
          </button>
          <button
            onClick={toggleReplay}
            className={`control-button ${showReplay ? 'active' : ''}`}
            title="视频回放"
            disabled={recordedBlobs.length === 0}
          >
            <PlayCircleOutlined />
          </button>
          {recordedBlobs.length > 0 && (
            <button
              onClick={downloadReplay}
              className="control-button"
              title="下载回放视频"
            >
              <DownloadOutlined />
            </button>
          )}
        </div>
      </div>

      {/* 美颜调节滑块 - 在美颜开启时显示 */}
      {beautyEnabled && (
        <div className="beauty-controls">
          <div className="beauty-slider">
            <label>
              美白
              <input
                type="range"
                min="0"
                max="0.3"
                step="0.01"
                value={whitenStrength}
                onChange={e => setWhitenStrength(Number(e.target.value))}
              />
            </label>
          </div>
          <div className="beauty-slider">
            <label>
              磨皮
              <input
                type="range"
                min="0"
                max="0.7"
                step="0.01"
                value={blurStrength}
                onChange={e => setBlurStrength(Number(e.target.value))}
              />
            </label>
          </div>
        </div>
      )}

      {/* 参会人员面板 */}
      {showParticipants && (
        <div className="participants">
          <h3>
            参会人员 ({usersInRoom.length})
            <button onClick={() => setShowParticipants(false)}>×</button>
          </h3>
          <ul>
            {usersInRoom.map(user => (
              <li key={user} className="participant-item">
                <div className="participant-info">
                  <span>
                    {user} {user === userId && '(你)'}
                  </span>
                  {/* 参会者列表中的鲜花显示 */}
                  <div className="participant-flowers">
                    <HeartOutlined
                      style={{ color: '#ff6b6b', marginRight: 4 }}
                    />
                    <span>{flowerCounts[user] || 0}</span>
                  </div>
                </div>
                {user !== userId && (
                  <button
                    className="participant-send-flower"
                    onClick={() => openFlowerPanel(user)}
                    title="送花"
                  >
                    <HeartOutlined />
                  </button>
                )}
              </li>
            ))}
          </ul>
        </div>
      )}
      {/* 聊天面板 */}
      {showChat && (
        <div className="chat-container">
          <div className="chat-header">
            <h3>会议聊天</h3>
            <button onClick={() => setShowChat(false)} className="close-button">
              ×
            </button>
          </div>
          <div className="chat-messages" ref={chatContainerRef}>
            {chatMessages.map((msg, index) => (
              <div key={index}>{renderMessage(msg)}</div>
            ))}
          </div>
          <form onSubmit={sendMessage} className="chat-input-form">
            <input
              type="text"
              value={newMessage}
              onChange={e => setNewMessage(e.target.value)}
              placeholder="输入消息..."
              className="chat-input"
            />
            <button
              type="button"
              className="emoji-button"
              onClick={() => setShowEmojiPicker(!showEmojiPicker)}
              title="选择表情"
            >
              <SmileOutlined />
            </button>
            <button type="submit" className="send-button">
              发送
            </button>
            {showEmojiPicker && (
              <div className="emoji-picker-container" ref={emojiPickerRef}>
                <EmojiPicker
                  onEmojiClick={handleEmojiClick}
                  width={280}
                  height={350}
                />
              </div>
            )}
          </form>
        </div>
      )}
      {/* 白板 */}
      {showWhiteboard && (
        <div className="whiteboard-container">
          <div className="whiteboard-header">
            <h3>协作白板</h3>
            <button onClick={toggleWhiteboard} className="close-button">
              ×
            </button>
          </div>
          <div className="whiteboard-tools">
            <div className="tool-group">
              <label className="tool-label">颜色</label>
              <input
                type="color"
                value={currentColor}
                onChange={e => setCurrentColor(e.target.value)}
                title="选择颜色"
                className="color-picker"
              />
            </div>
            <div className="tool-group">
              <label className="tool-label">粗细</label>
              <input
                type="range"
                min="1"
                max="20"
                value={lineWidth}
                onChange={e => setLineWidth(Number(e.target.value))}
                title="线条粗细"
                className="line-width-slider"
              />
              <span className="line-width-value">{lineWidth}px</span>
            </div>
            <div className="tool-group">
              <button
                onClick={clearWhiteboard}
                title="清除白板"
                className="tool-button"
              >
                <DeleteOutlined /> 清除
              </button>
            </div>
          </div>
          <canvas
            ref={canvasRef}
            onMouseDown={startDrawing}
            onMouseMove={draw}
            onMouseUp={finishDrawing}
            onMouseLeave={finishDrawing}
            className="whiteboard-canvas"
          />
          <div className="whiteboard-status">
            <p>其他用户可以看到您的绘制内容</p>
          </div>
        </div>
      )}
      {/* 举手弹窗 */}
      {showRaiseHand && raiseHandUser && (
        <div
          style={{
            position: 'fixed',
            top: 80,
            left: '50%',
            transform: 'translateX(-50%)',
            background: '#fffae6',
            color: '#333',
            padding: '16px 32px',
            borderRadius: 8,
            boxShadow: '0 2px 8px #0002',
            zIndex: 9999,
            fontSize: 20,
          }}
        >
          用户 {raiseHandUser} 举手了！
        </div>
      )}

      {/* 鲜花确认面板 */}
      {showFlowerPanel && selectedUserForFlower && (
        <div className="flower-confirm-panel">
          <div className="flower-confirm-content">
            <h3>送花确认</h3>
            <p>
              确定要向 <strong>用户 {selectedUserForFlower}</strong> 送花吗？
            </p>
            <div className="flower-confirm-buttons">
              <button
                onClick={() => sendFlower(selectedUserForFlower)}
                className="confirm-flower-button"
              >
                <HeartOutlined style={{ marginRight: 8 }} />
                确认送花
              </button>
              <button
                className="cancel-btn"
                onClick={() => {
                  setShowFlowerPanel(false);
                  setSelectedUserForFlower(null);
                }}
              >
                取消
              </button>
            </div>
          </div>
        </div>
      )}

      {/* 视频回放播放器 */}
      {showReplay && replayVideoUrl && (
        <div className="replay-container">
          <div className="replay-header">
            <h3>视频回放</h3>
            <button onClick={toggleReplay} className="close-button">
              ×
            </button>
          </div>
          <div className="replay-video-container">
            <video
              ref={replayVideoRef}
              src={replayVideoUrl}
              controls
              onTimeUpdate={handleReplayProgress}
              onPlay={() => setIsReplayPlaying(true)}
              onPause={() => setIsReplayPlaying(false)}
              className="replay-video"
            />
          </div>
          <div className="replay-controls">
            <button
              onClick={handleReplayPlayPause}
              className="replay-play-btn"
              title={isReplayPlaying ? '暂停' : '播放'}
            >
              {isReplayPlaying ? (
                <PauseCircleOutlined />
              ) : (
                <PlayCircleOutlined />
              )}
            </button>
            <div className="replay-progress-container">
              <input
                type="range"
                min="0"
                max="100"
                value={replayProgress}
                onChange={handleReplaySeek}
                className="replay-progress"
              />
            </div>
            <button
              onClick={downloadReplay}
              className="replay-download-btn"
              title="下载视频"
            >
              <DownloadOutlined />
            </button>
          </div>
          <div className="replay-info">
            <p>录制片段数: {recordedBlobs.length}</p>
            <p>
              总时长:{' '}
              {replayVideoRef.current?.duration
                ? `${Math.floor(replayVideoRef.current.duration / 60)}:${Math.floor(
                    replayVideoRef.current.duration % 60
                  )
                    .toString()
                    .padStart(2, '0')}`
                : '计算中...'}
            </p>
          </div>
        </div>
      )}

      {/* 会议纪要组件 */}
      {showTranscript && (
        <MeetingTranscript
          roomId={roomId}
          userId={userId}
          userName={userName}
          onToggleRecording={setIsTranscriptRecording}
        />
      )}
    </div>
  );
};

export default MeetingRoom;
